home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacWorld 2000 February
/
Macworld (2000-02).dmg
/
Cool Extras!
/
DarkSide of the Mac 5.0.6
/
SampleFaders
/
Fader.c
next >
Wrap
C/C++ Source or Header
|
1999-09-13
|
13KB
|
516 lines
/*
DarkSide - a 7.0 dependant, system clean expandable screen saver.
copyright © 1990-1997 by Tom Dowdy
All rights reserved.
This fader shell serves to dispatch requests from the main DarkSide code
into the appropriate entry points.
*/
#include <StdArg.h>
#include <Memory.h>
#include <Packages.h>
#include <Errors.h>
#include <TextUtils.h>
#include "Fader.h"
#ifdef THINK_C
#include <SetupA4.h>
#endif
#ifdef powerc
RoutineDescriptor preflightFaderUPP = BUILD_ROUTINE_DESCRIPTOR(uppPreflightFaderProcInfo,PreflightFader);
RoutineDescriptor initializeFaderUPP = BUILD_ROUTINE_DESCRIPTOR(uppInitializeFaderProcInfo,InitializeFader);
RoutineDescriptor idleFaderUPP = BUILD_ROUTINE_DESCRIPTOR(uppIdleFaderProcInfo,IdleFader);
RoutineDescriptor disposeFaderUPP = BUILD_ROUTINE_DESCRIPTOR(uppDisposeFaderProcInfo,DisposeFader);
RoutineDescriptor updateFaderUPP = BUILD_ROUTINE_DESCRIPTOR(uppUpdateFaderProcInfo,UpdateFader);
RoutineDescriptor hitFaderUPP = BUILD_ROUTINE_DESCRIPTOR(uppHitFaderProcInfo,HitFader);
#endif
QDGlobals qd;
/* ------------------------------------------------------------------------ */
/* GLOBAL HANDLING ROUTINES */
/* ------------------------------------------------------------------------ */
void DebugLongInt(long aLong);
#ifndef THINK_C
OSErr CreateA5World(Ptr * a5World);
void DisposeA5World(Ptr a5World, Ptr appA5);
#endif
/* ------------------------------------------------------------------------ */
#ifndef powerc
#ifdef THINK_C
OSErr main(long selector, Ptr *a5World, MachineInfoPtr machineInfo, ...)
#else
OSErr FaderEntry(long selector, Ptr *a5World, MachineInfoPtr machineInfo, ...)
#endif
{
OSErr anErr = noErr;
va_list nextArg;
#ifdef THINK_C
// Set up A4 so that we can use global variables...
RememberA0();
SetUpA4();
#endif
// start stripping optional arguments
va_start(nextArg, machineInfo);
switch(selector)
{
case preflightFader:
{
long *minTicks, *maxTicks;
minTicks = va_arg(nextArg, long*);
maxTicks = va_arg(nextArg, long*);
#ifndef THINK_C
#ifndef powerc
anErr = CreateA5World(a5World);
#endif
#endif
if (anErr == noErr)
{
#ifndef THINK_C
#ifndef powerc
(void) SetA5((long) *a5World);
#endif
#endif
BlockMove(machineInfo->applicationQD, &qd, sizeof(qd));
anErr = PreflightFader(machineInfo, minTicks, maxTicks);
BlockMove(&qd, machineInfo->applicationQD, sizeof(qd));
}
}
break;
case initializeFader:
#ifndef THINK_C
(void) SetA5((long) *a5World);
#endif
BlockMove(machineInfo->applicationQD, &qd, sizeof(qd));
anErr = InitializeFader(machineInfo);
BlockMove(&qd, machineInfo->applicationQD, sizeof(qd));
break;
case idleFader:
#ifndef THINK_C
(void) SetA5((long) *a5World);
#endif
anErr = IdleFader(machineInfo);
break;
case disposeFader:
{
#ifndef THINK_C
(void) SetA5((long) *a5World);
#endif
BlockMove(machineInfo->applicationQD, &qd, sizeof(qd));
anErr = DisposeFader(machineInfo);
BlockMove(&qd, machineInfo->applicationQD, sizeof(qd));
#ifndef THINK_C
DisposeA5World(*a5World, (Ptr)machineInfo->applicationA5);
#endif
}
break;
case updateFader:
#ifndef THINK_C
(void) SetA5((long) *a5World);
#endif
anErr = UpdateFader(machineInfo);
break;
case hitFader:
{
DialogPtr dPtr;
long itemHit;
long itemOffset;
dPtr = va_arg(nextArg, DialogPtr);
itemHit = va_arg(nextArg, long);
itemOffset = va_arg(nextArg, long);
anErr = HitFader(machineInfo, dPtr, itemHit, itemOffset);
}
break;
default:
// function not found error
anErr = fnfErr;
break;
}
va_end(nextArg);
#ifdef THINK_C
RestoreA4();
#else
(void) SetA5((long) machineInfo->applicationA5);
#endif
return(anErr);
} // FaderEntry
#endif
/* ------------------------------------------------------------------------ */
/* DEBUGGING ROUTINES */
/* ------------------------------------------------------------------------ */
void DebugLongInt(long theLong)
{
Str255 theString;
NumToString(theLong, theString);
DebugStr(theString);
} // DebugLongInt
/* ------------------------------------------------------------------------ */
/* FADER UTILS */
/* ------------------------------------------------------------------------ */
Handle BestNewHandle(Size theSize)
/*
Tries to get the handle from the temp memory first, if that fails, it goes
to the application.
*/
{
Handle theHandle;
OSErr anErr;
theHandle = TempNewHandle(theSize, &anErr);
if (theHandle == nil)
theHandle = NewHandle(theSize);
return(theHandle);
} // BestNewHandle
/* ------------------------------------------------------------------------ */
RgnHandle BestNewRgn()
/*
Tries to get a rgn handle from the temp memory first, if that fails, it goes
to the application. Needs enough room in the app heap to create the region
in the first place.
*/
{
RgnHandle theRgn;
OSErr anErr;
// make a region
theRgn = NewRgn();
if (theRgn != nil)
{
RgnHandle theHandle;
short regionSize;
// try to make something the same size in the temp memory
regionSize = GetHandleSize((Handle) theRgn);
theHandle = (RgnHandle) TempNewHandle(regionSize, &anErr);
if (anErr == noErr)
{
// if we get it, use that one for our region
BlockMove(*theRgn, *theHandle, regionSize);
DisposeRgn(theRgn);
theRgn = theHandle;
}
}
return(theRgn);
} // BestNewRgn
/* ------------------------------------------------------------------------ */
short Rnd(long max)
/*
Returns a number > 0 and < max
*/
{
unsigned long value;
value = (unsigned short)max * (unsigned short)Random();
value >>= 16;
return(value);
} // Rnd
/* ------------------------------------------------------------------------ */
void PlaceRectOnScreen(
MachineInfoPtr machineInfo, // give info about the machine here
short width, // width of rect, can be 0
short height, // height of rect, can be 0
Rect * placedRect, // Placed rect is returned here
Rect * margins, // margins around screen, can be nil
short * whichScreen) // screen index returned here, can be nil
{
Rect screenRect;
short pickScreen;
// pick a random screen
pickScreen = Rnd(machineInfo->numScreens);
screenRect = machineInfo->theScreens[pickScreen].bounds;
if (whichScreen != nil)
*whichScreen = pickScreen;
if (margins != nil)
{
screenRect.top += margins->top;
screenRect.left += margins->left;
screenRect.bottom -= margins->bottom;
screenRect.right -= margins->right;
}
screenRect.right -= width;
screenRect.bottom -= height;
if (placedRect != nil)
{
placedRect->top = screenRect.top + Rnd(screenRect.bottom - screenRect.top);
placedRect->left = screenRect.left + Rnd(screenRect.right - screenRect.left);
placedRect->bottom = placedRect->top + height;
placedRect->right = placedRect->left + width;
}
} // PlaceRectOnScreen
#ifndef THINK_C
#ifndef powerc
/* ------------------------------------------------------------------------ */
/* FUN A5 STUFF - See Tech note 256 for details */
/* ------------------------------------------------------------------------ */
long A5Size();
void A5Init(Ptr theA5);
OSErr CreateA5World(Ptr * a5World)
{
OSErr anErr;
Ptr theWorld = nil;
Handle worldHandle;
worldHandle = BestNewHandle(A5Size());
anErr = MemError();
if (anErr == noErr)
{
HLockHi(worldHandle);
theWorld = *worldHandle;
theWorld += + A5Size() - 32;
A5Init(theWorld);
// very important if anyone wants to call SwapMMUMode
theWorld = StripAddress(theWorld);
}
*a5World = theWorld;
return(anErr);
} // CreateA5World
/* ------------------------------------------------------------------------ */
void DisposeA5World(Ptr a5World, Ptr appA5)
{
(void) SetA5((long) appA5);
{
Handle theHandle = RecoverHandle(a5World - A5Size() + 32);
DisposeHandle(theHandle);
}
} // DisposeA5World
#endif
#endif
#ifdef THINK_C
/* ------------------------------------------------------------------------ */
/* CALLBACK WRAPPERS */
/* ------------------------------------------------------------------------ */
OSErr WritePreferencesHandle(MachineInfoPtr machineInfo, Handle h, ResType theType)
{
OSErr anErr;
long curA5;
long loader;
curA5 = SetA5((long) machineInfo->applicationA5);
loader = (long) machineInfo->callbackLoader;
asm {
move.l theType, -(SP)
move.l h, -(SP)
move.l loader, a0
moveq #0, d0
pea @returnAddress
move.l #0x08000004, -(SP)
jmp (a0)
@returnAddress:
move.w d0, anErr
add #8, SP
}
SetA5(curA5);
return(anErr);
} // WritePreferencesHandle
/* ------------------------------------------------------------------------ */
OSErr ReadPreferencesHandle(MachineInfoPtr machineInfo, Handle *h, ResType theType)
{
OSErr anErr;
long curA5;
long loader;
curA5 = SetA5((long) machineInfo->applicationA5);
loader = (long) machineInfo->callbackLoader;
asm {
move.l theType, -(SP)
move.l h, -(SP)
move.l loader, a0
moveq #0, d0
pea @returnAddress
move.l #0x08000008, -(SP)
jmp (a0)
@returnAddress:
move.w d0, anErr
add #8, SP
}
SetA5(curA5);
return(anErr);
} // ReadPreferencesHandle
/* ------------------------------------------------------------------------ */
// While translating this code from MPW C to THINK C I found out that the calling conventions
// of these languages seem to be different. If we have a short and a Boolean as below, THINK C
// pushes them both into a longword, while MPW C uses a longword for each. Very confusing!
OSErr PlayResourceSnd(MachineInfoPtr machineInfo, long theID, Boolean async)
{
OSErr anErr;
long loader;
loader = (long) machineInfo->callbackLoader;
asm {
moveq #0, d0
move.b async, d0 // convert async to longword
move.l d0, -(SP) // and push it
moveq #0, d0 // convert theID to longword
move.w theID, d0 // and push it
move.l d0, -(SP)
move.l loader, a0
moveq #0, d0
pea @returnAddress // push return address
move.l #0x0800000C, -(SP) // push selector code
jmp (a0) // jump to callback loader
@returnAddress:
move.w d0, anErr // save result code
add #8, SP // adjust stack
}
return anErr;
} // PlayResourceSnd
#else
/* ------------------------------------------------------------------------ */
/* CALLBACK DEFINES */
/* ------------------------------------------------------------------------ */
#ifndef powerc
#pragma parameter __D0 DoWritePreferencesHandle(__A0)
OSErr DoWritePreferencesHandle(Ptr M, Handle h, ResType theType) =
{ 0x7000, 0x487B, 0x000A, 0x2F3C, 0x0800, 0x0004, 0x4ED0};
#pragma parameter __D0 DoReadPreferencesHandle(__A0)
OSErr DoReadPreferencesHandle(Ptr M, Handle *h, ResType theType) =
{ 0x7000, 0x487B, 0x000A, 0x2F3C, 0x0800, 0x0008, 0x4ED0};
// #pragma parameter __D0 DoPlayResourceSnd(__A0)
OSErr DoPlayResourceSnd(Ptr M, long theID, long async) =
{ 0x205f, // MOVEA.L (SP)+, A0
0x7000, // MOVEQ 0, D0
0x487B, 0x000A, // PEA *+C(D0)
0x2F3C, 0x0800, 0x000C, // MOVE SELECTOR, -(SP)
0x4ED0}; // JMP (A0)
#endif
/* ------------------------------------------------------------------------ */
/* CALLBACK WRAPERS */
/* ------------------------------------------------------------------------ */
OSErr WritePreferencesHandle(MachineInfoPtr machineInfo, Handle h, ResType theType)
{
OSErr anErr;
#ifdef powerc
anErr = CallUniversalProc((UniversalProcPtr) machineInfo->callbackLoader, uppCallbackInfo, callbackWritePreferencesHandle, h, theType);
#else
long curA5;
curA5 = SetA5((long)machineInfo->applicationA5);
anErr = DoWritePreferencesHandle(machineInfo->callbackLoader, h, theType);
SetA5(curA5);
#endif
return(anErr);
} // WritePreferencesHandle
/* ------------------------------------------------------------------------ */
OSErr ReadPreferencesHandle(MachineInfoPtr machineInfo, Handle *h, ResType theType)
{
OSErr anErr;
#ifdef powerc
anErr = CallUniversalProc((UniversalProcPtr) machineInfo->callbackLoader, uppCallbackInfo, callbackReadPreferencesHandle, h, theType);
#else
long curA5;
curA5 = SetA5((long)machineInfo->applicationA5);
anErr = DoReadPreferencesHandle(machineInfo->callbackLoader, h, theType);
SetA5(curA5);
#endif
return(anErr);
} // ReadPreferencesHandle
/* ------------------------------------------------------------------------ */
OSErr PlayResourceSnd(MachineInfoPtr machineInfo, long theID, long async)
{
OSErr anErr;
#ifdef powerc
anErr = CallUniversalProc((UniversalProcPtr) machineInfo->callbackLoader, uppCallbackInfo, callbackPlayResourceSnd, (long)theID, (long)async);
#else
long curA5;
curA5 = SetA5((long)machineInfo->applicationA5);
anErr = DoPlayResourceSnd(machineInfo->callbackLoader, theID, async);
SetA5(curA5);
#endif
return(anErr);
} // PlayResourceSnd
#endif